<?php

namespace VersionManager\Core\Version\Util;

/**
 * PHP配置助手类
 *
 * 提供PHP配置相关的通用功能
 */
class PhpConfigHelper
{
    /**
     * 配置PHP
     *
     * @param string $version PHP版本
     * @param string $versionDir 版本目录
     * @return bool
     */
    public static function configurePhp($version, $versionDir)
    {
        // 创建配置目录
        $configDir = $versionDir . '/etc';
        FileHelper::ensureDirectoryExists($configDir);

        // 创建扩展配置目录
        $confDir = $configDir . '/conf.d';
        FileHelper::ensureDirectoryExists($confDir);

        // 创建php.ini
        self::createPhpIni($version, $versionDir, $configDir);

        // 创建php-fpm配置（如果需要）
        self::createPhpFpmConfig($version, $versionDir, $configDir);

        return true;
    }

    /**
     * 创建php.ini配置文件
     *
     * @param string $version PHP版本
     * @param string $versionDir 版本目录
     * @param string $configDir 配置目录
     * @return bool
     */
    public static function createPhpIni($version, $versionDir, $configDir)
    {
        $phpIni = $configDir . '/php.ini';

        // 尝试复制php.ini-development
        $phpIniDev = $versionDir . '/lib/php.ini-development';
        if (file_exists($phpIniDev)) {
            copy($phpIniDev, $phpIni);
            $iniContent = file_get_contents($phpIni);
        } else {
            // 如果没有找到php.ini-development，则创建基础配置
            $iniContent = self::getDefaultPhpIniContent($version);
        }

        // 修改配置
        $iniContent = self::updatePhpIniSettings($iniContent, $version, $versionDir);

        // 保存修改后的php.ini
        file_put_contents($phpIni, $iniContent);

        return true;
    }

    /**
     * 获取默认的php.ini内容
     *
     * @param string $version PHP版本
     * @return string
     */
    public static function getDefaultPhpIniContent($version)
    {
        return "; PHP Configuration File\n" .
               "; Generated by PVM for PHP {$version}\n" .
               "; " . date('Y-m-d H:i:s') . "\n\n" .
               "[PHP]\n" .
               "engine = On\n" .
               "short_open_tag = Off\n" .
               "precision = 14\n" .
               "output_buffering = 4096\n" .
               "zlib.output_compression = Off\n" .
               "implicit_flush = Off\n" .
               "unserialize_callback_func =\n" .
               "serialize_precision = -1\n" .
               "disable_functions =\n" .
               "disable_classes =\n" .
               "zend.enable_gc = On\n" .
               "expose_php = On\n" .
               "max_execution_time = 30\n" .
               "max_input_time = 60\n" .
               "memory_limit = 128M\n" .
               "error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT\n" .
               "display_errors = Off\n" .
               "display_startup_errors = Off\n" .
               "log_errors = On\n" .
               "log_errors_max_len = 1024\n" .
               "ignore_repeated_errors = Off\n" .
               "ignore_repeated_source = Off\n" .
               "report_memleaks = On\n" .
               "variables_order = \"GPCS\"\n" .
               "request_order = \"GP\"\n" .
               "register_argc_argv = Off\n" .
               "auto_globals_jit = On\n" .
               "post_max_size = 8M\n" .
               "auto_prepend_file =\n" .
               "auto_append_file =\n" .
               "default_mimetype = \"text/html\"\n" .
               "default_charset = \"UTF-8\"\n" .
               "doc_root =\n" .
               "user_dir =\n" .
               "enable_dl = Off\n" .
               "file_uploads = On\n" .
               "upload_max_filesize = 2M\n" .
               "max_file_uploads = 20\n" .
               "allow_url_fopen = On\n" .
               "allow_url_include = Off\n" .
               "default_socket_timeout = 60\n\n";
    }

    /**
     * 更新php.ini设置
     *
     * @param string $iniContent 原始ini内容
     * @param string $version PHP版本
     * @param string $versionDir 版本目录
     * @return string 更新后的ini内容
     */
    public static function updatePhpIniSettings($iniContent, $version, $versionDir)
    {
        // 设置扩展目录
        $extensionDir = $versionDir . '/lib/php/extensions';
        $iniContent = preg_replace('/;?\s*extension_dir\s*=.*/', "extension_dir = \"{$extensionDir}\"", $iniContent);

        // 设置include_path
        $includePath = $versionDir . '/lib/php';
        $iniContent = preg_replace('/;?\s*include_path\s*=.*/', "include_path = \".:{$includePath}\"", $iniContent);

        // 设置date.timezone
        $iniContent = preg_replace('/;?\s*date\.timezone\s*=.*/', "date.timezone = \"UTC\"", $iniContent);

        // 设置扩展配置目录
        $confDir = $versionDir . '/etc/conf.d';
        if (!preg_match('/scan_dir\s*=/', $iniContent)) {
            $iniContent .= "\n; Scan this dir for additional .ini files\n";
            $iniContent .= "scan_dir = \"{$confDir}\"\n";
        }

        // 根据PHP版本添加特定设置
        if (VersionHelper::isPhp8OrHigher($version)) {
            // PHP 8+ 特定设置
            if (!preg_match('/zend\.exception_ignore_args/', $iniContent)) {
                $iniContent .= "\n; PHP 8+ specific settings\n";
                $iniContent .= "zend.exception_ignore_args = Off\n";
            }
        }

        return $iniContent;
    }

    /**
     * 创建php-fpm配置文件
     *
     * @param string $version PHP版本
     * @param string $versionDir 版本目录
     * @param string $configDir 配置目录
     * @return bool
     */
    public static function createPhpFpmConfig($version, $versionDir, $configDir)
    {
        $fpmConfigFile = $configDir . '/php-fpm.conf';
        $poolConfigFile = $configDir . '/php-fpm.d/www.conf';

        // 创建php-fpm.d目录
        FileHelper::ensureDirectoryExists($configDir . '/php-fpm.d');

        // 创建主配置文件
        $fpmConfig = self::getDefaultPhpFpmConfig($version, $versionDir);
        file_put_contents($fpmConfigFile, $fpmConfig);

        // 创建池配置文件
        $poolConfig = self::getDefaultPoolConfig($version, $versionDir);
        file_put_contents($poolConfigFile, $poolConfig);

        return true;
    }

    /**
     * 获取默认的php-fpm配置
     *
     * @param string $version PHP版本
     * @param string $versionDir 版本目录
     * @return string
     */
    public static function getDefaultPhpFpmConfig($version, $versionDir)
    {
        return "; PHP-FPM Configuration File\n" .
               "; Generated by PVM for PHP {$version}\n" .
               "; " . date('Y-m-d H:i:s') . "\n\n" .
               "[global]\n" .
               "pid = {$versionDir}/var/run/php-fpm.pid\n" .
               "error_log = {$versionDir}/var/log/php-fpm.log\n" .
               "daemonize = yes\n" .
               "include = {$versionDir}/etc/php-fpm.d/*.conf\n\n";
    }

    /**
     * 获取默认的池配置
     *
     * @param string $version PHP版本
     * @param string $versionDir 版本目录
     * @return string
     */
    public static function getDefaultPoolConfig($version, $versionDir)
    {
        return "; Pool Configuration\n" .
               "; Generated by PVM for PHP {$version}\n" .
               "; " . date('Y-m-d H:i:s') . "\n\n" .
               "[www]\n" .
               "user = www-data\n" .
               "group = www-data\n" .
               "listen = 127.0.0.1:9000\n" .
               "listen.owner = www-data\n" .
               "listen.group = www-data\n" .
               "listen.mode = 0660\n" .
               "pm = dynamic\n" .
               "pm.max_children = 5\n" .
               "pm.start_servers = 2\n" .
               "pm.min_spare_servers = 1\n" .
               "pm.max_spare_servers = 3\n" .
               "pm.process_idle_timeout = 10s\n" .
               "pm.max_requests = 500\n" .
               "slowlog = {$versionDir}/var/log/slow.log\n" .
               "request_slowlog_timeout = 5s\n" .
               "php_admin_value[error_log] = {$versionDir}/var/log/error.log\n" .
               "php_admin_flag[log_errors] = on\n\n";
    }

    /**
     * 创建扩展配置文件
     *
     * @param string $extension 扩展名
     * @param string $configDir 配置目录
     * @param array $settings 扩展设置
     * @return bool
     */
    public static function createExtensionConfig($extension, $configDir, array $settings = [])
    {
        $confDir = $configDir . '/conf.d';
        FileHelper::ensureDirectoryExists($confDir);

        $configFile = $confDir . '/' . $extension . '.ini';
        $content = "; {$extension} extension configuration\n";
        $content .= "extension={$extension}\n";

        foreach ($settings as $key => $value) {
            $content .= "{$key} = {$value}\n";
        }

        file_put_contents($configFile, $content);

        return true;
    }

    /**
     * 获取PHP信息
     *
     * @param string $phpBinary PHP二进制文件路径
     * @return array PHP信息
     */
    public static function getPhpInfo($phpBinary)
    {
        $info = [];

        // 获取PHP版本
        $output = [];
        exec($phpBinary . ' -v 2>/dev/null', $output);
        if (!empty($output)) {
            $info['version_string'] = $output[0];
        }

        // 获取配置文件路径
        $output = [];
        exec($phpBinary . ' --ini 2>/dev/null', $output);
        foreach ($output as $line) {
            if (strpos($line, 'Configuration File') !== false) {
                $info['config_file'] = trim(str_replace('Configuration File (php.ini) Path:', '', $line));
            } elseif (strpos($line, 'Loaded Configuration File') !== false) {
                $info['loaded_config_file'] = trim(str_replace('Loaded Configuration File:', '', $line));
            } elseif (strpos($line, 'Scan this dir') !== false) {
                $info['scan_dir'] = trim(str_replace('Scan this dir for additional .ini files:', '', $line));
            }
        }

        // 获取扩展列表
        $output = [];
        exec($phpBinary . ' -m 2>/dev/null', $output);
        $extensions = [];
        $inExtensions = false;

        foreach ($output as $line) {
            $line = trim($line);
            if ($line === '[PHP Modules]') {
                $inExtensions = true;
                continue;
            }
            if ($line === '[Zend Modules]') {
                $inExtensions = false;
                continue;
            }
            if ($inExtensions && !empty($line)) {
                $extensions[] = $line;
            }
        }
        $info['extensions'] = $extensions;

        return $info;
    }

    /**
     * 验证PHP配置
     *
     * @param string $phpBinary PHP二进制文件路径
     * @return array 验证结果
     */
    public static function validatePhpConfig($phpBinary)
    {
        $output = [];
        $returnCode = 0;

        exec($phpBinary . ' -t 2>&1', $output, $returnCode);

        return [
            'valid' => $returnCode === 0,
            'output' => implode("\n", $output)
        ];
    }

    /**
     * 获取推荐的php.ini设置
     *
     * @param string $environment 环境类型（development/production）
     * @return array 推荐设置
     */
    public static function getRecommendedSettings($environment = 'production')
    {
        $settings = [
            'development' => [
                'display_errors' => 'On',
                'display_startup_errors' => 'On',
                'error_reporting' => 'E_ALL',
                'log_errors' => 'On',
                'memory_limit' => '256M',
                'max_execution_time' => '60',
                'post_max_size' => '32M',
                'upload_max_filesize' => '32M',
                'opcache.enable' => '1',
                'opcache.revalidate_freq' => '0',
                'opcache.validate_timestamps' => '1',
            ],
            'production' => [
                'display_errors' => 'Off',
                'display_startup_errors' => 'Off',
                'error_reporting' => 'E_ALL & ~E_DEPRECATED & ~E_STRICT',
                'log_errors' => 'On',
                'memory_limit' => '128M',
                'max_execution_time' => '30',
                'post_max_size' => '8M',
                'upload_max_filesize' => '2M',
                'opcache.enable' => '1',
                'opcache.revalidate_freq' => '60',
                'opcache.validate_timestamps' => '0',
                'opcache.memory_consumption' => '128',
                'opcache.interned_strings_buffer' => '8',
                'opcache.max_accelerated_files' => '4000',
            ]
        ];

        return isset($settings[$environment]) ? $settings[$environment] : $settings['production'];
    }
}
